package com.cssy.xxkj.logic.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.byd.acegiext.domain.User;
import com.cssy.xxkj.logic.contants.BillStatusUtil;
import com.cssy.xxkj.logic.contants.BillTypeConstant;
import com.cssy.xxkj.logic.dao.LogicOutsideBoundDAO;
import com.cssy.xxkj.logic.dao.LogicOutsideBoundItemDAO;
import com.cssy.xxkj.logic.dao.LogicOutsideStockDAO;
import com.cssy.xxkj.logic.dao.LogicOutsideStockItemDAO;
import com.cssy.xxkj.logic.entity.LogicOutsideBoundDO;
import com.cssy.xxkj.logic.entity.LogicOutsideBoundItemDO;
import com.cssy.xxkj.logic.entity.LogicOutsideStockDO;
import com.cssy.xxkj.logic.entity.LogicOutsideStockItemDO;
import com.cssy.xxkj.logic.service.ILogicHsUtilService;
import com.cssy.xxkj.logic.service.ILogicOutsideBoundService;
import com.plat.exception.SyBaseException;
import com.plat.helper.SearchConditions;
import com.plat.helper.SearchResult;
import com.plat.util.DateUtils;
import com.plat.util.GlobalResLoader;
import com.plat.util.IDCodeTypeUtil;
import com.plat.util.SessionUtil;
import com.yuendong.sy.po.code.SyCode;
import com.yuendong.sy.service.code.impl.SyCodeService;

@Service("logicOutsideBoundService")
public class LogicOutSideBoundServiceImpl implements ILogicOutsideBoundService {
	
	@Resource(name = "logicOutsideStockDAO")
	private LogicOutsideStockDAO logicOutsideStockDAO;
	
	@Resource(name = "logicOutsideStockItemDAO")
	private LogicOutsideStockItemDAO logicOutsideStockItemDAO;
	
	@Resource(name = "logicOutsideBoundDAO")
	private LogicOutsideBoundDAO logicOutsideBoundDAO;
	
	@Resource(name = "logicOutsideBoundItemDAO")
	private LogicOutsideBoundItemDAO logicOutsideBoundItemDAO;
	
	@Resource(name = "logicHsUtilService")
	private ILogicHsUtilService logicHsUtilService;
	
	@Resource(name = "syCodeService")
	private SyCodeService syCodeService;

	@Override
	public SearchResult findListByExample(SearchConditions scs)
			throws SyBaseException {
		SearchResult rs=new SearchResult(scs);
		List<LogicOutsideBoundDO>  list = logicOutsideBoundDAO.find(scs);
		rs.setRecordCount(logicOutsideBoundDAO.count(scs));
		rs.setResults(list);
		return rs;
	}

	@Override
	public Integer delete(String id, User user) throws SyBaseException {
		return logicOutsideBoundDAO.deleteBizRemoved(id);
	}

	@Override
	public Integer update(LogicOutsideBoundDO outSideBound, User user)
			throws SyBaseException {
		outSideBound.setBizModifyDate(new Date());
		outSideBound.setBizModifyName(user.getName());
		outSideBound.setBizVersionMark(outSideBound.getBizVersion());
		outSideBound.setBizVersion(outSideBound.getBizVersion()+1);
		return logicOutsideBoundDAO.updateLogicOutsideBoundDO(outSideBound);
	}

	@Override
	public LogicOutsideBoundDO save(LogicOutsideBoundDO sideBound, User user)
			throws SyBaseException {
		sideBound.setBizCreatorDate(new Date());
		sideBound.setBizCreatorName(user.getName());
		sideBound.setBizVersion(Integer.valueOf(1));
		this.logicOutsideBoundDAO.insertLogicOutsideBoundDO(sideBound);
		return sideBound;
	}
	
	@Override
	public void outSideOutSave(LogicOutsideBoundDO curAP, HttpServletRequest request)
			throws SyBaseException{
		String dataitem = request.getParameter("dataitem");
		String detadele = request.getParameter("datadele");
		String zd006Date = request.getParameter("zd006Date");
		String submitFlag = request.getParameter("submitFlag");
		if(StringUtils.isNotBlank(zd006Date)){
			curAP.setZd006Date(DateUtils.stringToDate(zd006Date));
		}else{
			curAP.setZd006Date(new Date());
		}
		try{
			if(BillStatusUtil.OUTSIDEOUT_STATUS_THREE.equals(submitFlag)){
				//驳回
				LogicOutsideBoundDO outSideBound = logicOutsideBoundDAO.findLogicOutsideBoundDOByPrimaryKey(curAP.getId());
				if(outSideBound==null){
					throw new SyBaseException("数据发生改变，请重新提交。");
				}
				curAP.setZd001Status(submitFlag);
				this.update(outSideBound, SessionUtil.getUser(request));
			}else{
				String zd001Id = "";
				String zd001Code = "";
				curAP.setZd001Status(submitFlag);
				if(curAP==null || StringUtils.isBlank(curAP.getId())){
					//新增
					zd001Id = IDCodeTypeUtil.getId();
					curAP.setId(zd001Id);
					zd001Code = syCodeService.getCode(BillTypeConstant.OUTSIDEOUT,BillTypeConstant.OUTSIDEOUT,SyCode.DATE_YYMM,5);
					curAP.setZd001Code(zd001Code);
					this.save(curAP, SessionUtil.getUser(request));
				}else{
					//修改
					zd001Id = curAP.getId();
					zd001Code = curAP.getZd001Code();
					Integer rowUp = this.update(curAP, SessionUtil.getUser(request));
					if(rowUp==null||rowUp.intValue()==0){
						throw new SyBaseException("数据发生改变，请重新提交。");
					}else{
						if(StringUtils.isNotBlank(detadele)){
							List<LogicOutsideBoundItemDO> boundItemList = JSONArray.parseArray(detadele,LogicOutsideBoundItemDO.class);
							for(LogicOutsideBoundItemDO boundItem : boundItemList){
								if(boundItem==null||StringUtils.isBlank(boundItem.getId())){
									continue;
								}
								logicOutsideBoundItemDAO.deleteLogicOutsideBoundItemDOByPrimaryKey(boundItem.getId());
							}
						}
					}
				}
				
				//新增
				List<LogicOutsideBoundItemDO> boundItemList = JSONArray.parseArray(dataitem,LogicOutsideBoundItemDO.class);
				Map<String,Object> paramMap = new HashMap<String,Object>();
				paramMap.put("zd001Id",zd001Id);
				paramMap.put("zd001Code",zd001Code);
				if(BillStatusUtil.OUTSIDEOUT_STATUS_FOUR.equals(submitFlag)){
					//需要修改库存
					paramMap.put("user", SessionUtil.getUser(request));
					this.outSideBoundSaveOrUpdateOrStock(boundItemList, paramMap, true);
				}else{
					//不需要修改库存
					this.outSideBoundSaveOrUpdateOrStock(boundItemList, paramMap, false);
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			throw new SyBaseException(GlobalResLoader.getOpfailed()+ e.getMessage());
		}
	}
	
	/**
	 * 新增/修改委外入库item，同时是否修改库存
	 * @param outItemList
	 * @param paramMap
	 * @param upStock
	 * @throws SyBaseException
	 */
	private void outSideBoundSaveOrUpdateOrStock(List<LogicOutsideBoundItemDO> boundItemList, Map<String,Object> paramMap,boolean upStock)
			throws SyBaseException{
		try{
			String zd001Id = paramMap.get("zd001Id")+"";
			LogicOutsideBoundDO outBound = logicOutsideBoundDAO.findLogicOutsideBoundDOByPrimaryKey(zd001Id);
			//查询委外入库单的item，封装成map对象
			Map<String, LogicOutsideStockItemDO> outSdInItemMap = this.findQuearyOutSdInToMap(zd001Id);
			for(LogicOutsideBoundItemDO boundItem : boundItemList){
				if(boundItem==null){
					continue;
				}
				if(StringUtils.isBlank(boundItem.getId())){
					//新增item
					boundItem.setId(IDCodeTypeUtil.getId());
					boundItem.setZd001SideOutId(paramMap.get("zd001Id")+"");
					boundItem.setZd001SideOutCode(paramMap.get("zd001Code")+"");
					this.logicOutsideBoundItemDAO.insertLogicOutsideBoundItemDO(boundItem);
				}else{
					//修改item
					this.logicOutsideBoundItemDAO.updateLogicOutsideBoundItemDO(boundItem);
					if(upStock){
						//判断能否委外出库
						String keyStr = zd001Id + "_" +boundItem.getZd003MaterId();
						LogicOutsideStockItemDO outSdInItem = outSdInItemMap.get(keyStr);
						if(outSdInItem==null||StringUtils.isBlank(outSdInItem.getId())){
							throw new SyBaseException("该出库单的物料没有在委外入库单中找到。");
						}else{
							//委外单入库总数
							BigDecimal inQuantity = outSdInItem.getZd018InQuantity()==null?BigDecimal.ZERO:outSdInItem.getZd018InQuantity();
							//委外单已出库数量
							BigDecimal hasOutQuantity = outSdInItem.getZd018HasOutQuantity()==null?BigDecimal.ZERO:outSdInItem.getZd018HasOutQuantity();
							//本次出库数量
							BigDecimal theOutQuantity = boundItem.getZd018OutQuantity();
							//比较：总数与已出库数量+本次出库数量和去比较
							int comQuantity =  inQuantity.compareTo(hasOutQuantity.add(theOutQuantity));
							if(comQuantity==-1){
								//表示总数小于已出库数量+本次出库数量
								throw new SyBaseException("错误：当前出库单的出库数量已大于入库数量。");
							}else{
								//修改委外入库单的已出库、未出库数量
								outSdInItem.setZd018HasOutQuantity(hasOutQuantity.add(theOutQuantity));
								outSdInItem.setZd018NoOutQuantity(inQuantity.subtract(outSdInItem.getZd018HasOutQuantity()));
								//更新map中的新数据
								outSdInItemMap.put(keyStr, outSdInItem);
								logicOutsideStockItemDAO.updateLogicOutsideStockItemDO(outSdInItem);
								//修改委外出库单的已出库、未出库数量
								BigDecimal _hasOutQuantity = boundItem.getZd018HasOutQuantity()==null?BigDecimal.ZERO:boundItem.getZd018HasOutQuantity();
								boundItem.setZd018HasOutQuantity(_hasOutQuantity.add(theOutQuantity));
								boundItem.setZd018NoOutQuantity(boundItem.getZd018InQuantity().subtract(boundItem.getZd018HasOutQuantity()));
								logicOutsideBoundItemDAO.updateLogicOutsideBoundItemDO(boundItem);
							}
							//修改委外出入库单的出库状态
							boolean upSt = true;
							for(LogicOutsideStockItemDO _outSdInItem : outSdInItemMap.values()){
								if(_outSdInItem==null||StringUtils.isBlank(_outSdInItem.getId())){
									continue;
								}
								BigDecimal outSdInHasOutQuantity = _outSdInItem.getZd018HasOutQuantity()==null?BigDecimal.ZERO:_outSdInItem.getZd018HasOutQuantity();
								int upOutSdState = _outSdInItem.getZd018InQuantity().compareTo(outSdInHasOutQuantity);
								if(upOutSdState==1){
									upSt = false;
								}
							}
							LogicOutsideStockDO outSdIn = logicOutsideStockDAO.findLogicOutsideStockDOByPrimaryKey(outBound.getZd002OriginId());
							if(outSdIn==null||StringUtils.isBlank(outSdIn.getId())){
								throw new SyBaseException("查询不到该委外入库单，请确认。");
							}
							if(upSt){
								outSdIn.setZd001OutStatus(BillStatusUtil.OUTSIDEIN_WH_STATUS_TWO);
							}else{
								outSdIn.setZd001OutStatus(BillStatusUtil.OUTSIDEIN_WH_STATUS_ONE);
							}
							outSdIn.setBizVersionMark(outSdIn.getBizVersion());
							this.logicOutsideStockDAO.updateLogicOutsideStockDO(outSdIn);
						}
						//修改库存
						User user = (User)paramMap.get("user");
						this.logicHsUtilService.processHsOutSideOutItem(outBound, boundItem, user);
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			
		}
	}
	
	private Map<String, LogicOutsideStockItemDO> findQuearyOutSdInToMap(String originId){
		Map<String, LogicOutsideStockItemDO> outSdInMap = new HashMap<String, LogicOutsideStockItemDO>();
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("", originId);
		List<LogicOutsideStockItemDO> outSdInItemList = logicOutsideStockItemDAO.findListByMap(paramMap);
		for(LogicOutsideStockItemDO outSdInItem : outSdInItemList){
			if(outSdInItem==null||StringUtils.isBlank(outSdInItem.getId())){
				continue;
			}
			String keyStr = originId + "_"+ outSdInItem.getZd003MaterId();
			outSdInMap.put(keyStr, outSdInItem);
		}
		return outSdInMap;
	}
	
	@Override
	public LogicOutsideBoundDO findListById(String id) throws SyBaseException {
		return logicOutsideBoundDAO.findLogicOutsideBoundDOByPrimaryKey(id);
	}

	@Override
	public Integer deleteBizRemoved(String id) throws SyBaseException {
		return logicOutsideBoundDAO.deleteBizRemoved(id);
	}
	
	/**
	 * 查询委外出库的item集合
	 */
	@Override
	public List<LogicOutsideBoundItemDO> findItemListByMap(Map<String, Object> paramMap)
			throws SyBaseException{
		return logicOutsideBoundItemDAO.findListByMap(paramMap);
	}

}
